package com.kg.fiber.service.clock;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.ivan.toolkit.common.SystemTime;
import com.kg.fiber.service.clock.ClockDriver.Time;

import lombok.extern.log4j.Log4j;


/*
int main(){
   FILE * pf;
	unsigned char dt[48];
	unsigned long n = 1;

   pf = fopen("/dev/PCI_SZK","r");     //第一个参数是路径，驱动安装成功之后PCI_SZK文件就存在于dev文件夹下面了，那么对这个文件的读写实际就是对PCI卡的操作，第二个参数是打�?的方�?
	if(pf < 0){
		printf("打开设备失败�?");
		exit(1);
	}
	while(1){
		fread(dt,1,16,pf);            //(buffer,size,count,FILE *stream)(size表示每个数据的大�?)

		printf("%02d%02d-%02d-%02d %02d:%02d:%02d.%04lu  ",dt[9],dt[8],dt[7],dt[6],dt[5],dt[4],dt[3],(dt[1] * 256 + dt[2])<<1);


		if((dt[0]&0x80)==0){
			printf("Slave "); 
		}else{
			printf("Master"); 
		}

		if((dt[0]&0x01)==0){
			printf("GPS ");
		}else{ 
			printf("RTC ");
		}
		printf("StN=%02d  Time Quality=%3d  %lu\n",dt[10],dt[11],n++);
		sleep(1);

	}
	fclose(pf);

}
 */

@Component
@Log4j
public class Clocker {
	
	long delta = 0L;
	
	static boolean timeSynchronized = false;
	
	@PostConstruct
	private void postConstruct() {

	}
	
	
	@PreDestroy
	private void preDestroy() {
		
		ClockDriver.terminate();
		
	}
	
	@Scheduled(cron="0/5 * *  * * ? ")   
    public void doScheduled() {
		
		ClockDriver.initialize();
		
		if(!ready()) return;
		
		try {
		
			Time tm = now();
			
			long pciNow = tm.getTimestamp();
			long sysNow = System.currentTimeMillis();
			
			long newDelta = pciNow - sysNow;
			
			long deltaDelta = Math.abs(newDelta - delta);
			
			if(deltaDelta > 1000) {
				
				log.info("Delta's delta > 1000,  caculate again");
				
				pciNow = tm.getTimestamp();
				sysNow = System.currentTimeMillis();		
				newDelta = pciNow - sysNow;		
			}
			
			delta = newDelta;
				
			if(deltaDelta > 5000) {
				log.info("Delta's delta > 5000,  new delta is " + delta);
			}
			
			//log.info("Adjust time : " + tm.datetime() + " , delta is " + delta);
			if(delta > 5000) {
				log.info("Synchronize time, delta > 5000, delta is " + delta);
			}
			
		} catch (Exception e) {
			log.warn("Adjust system time failed.", e);
		}
		
    }
	
	public void runtime(StringBuilder sb) {
		sb.append("[CLOCK]\r\n");
		sb.append("state=").append(ready()).append("\r\n");
		sb.append("delta=").append(delta).append("\r\n");
		sb.append("timeSynchronized=").append(timeSynchronized).append("\r\n");
		//sb.append("setTimeCount=").append(this.synchronizeSystemTimeCount).append("\r\n");
	}

	
	public boolean ready() {
		return ClockDriver.ready();
	}
	
	public Time now() throws Exception {
		
		return ClockDriver.now();
		
	}
	

	public long nowInMillis() {
		
		return System.currentTimeMillis() + delta;
		
	}
	
	
	public static void synchronizeSystemTime() {
		
		ClockDriver.initialize();
		
		if(!ClockDriver.ready()) {
			
			log.info("Open clock driver failed, ignore system time synchronize.");
			
			return;
			
		}
		
		
		for(int i = 0; i < 10; i++) {
			
			try {
			
				long nowClk = ClockDriver.now().getTimestamp();
				long nowSys = System.currentTimeMillis();
				if(Math.abs(nowSys - nowClk) > 5000) {
					
					SystemTime.set(nowClk);
					
					Thread.sleep(10);
					
				} else {
					
					break;
					
				}
			
			
			} catch(Exception e) {
				log.warn("Exception occor when synchronize system time", e);
			}
			
		}
		
		/*
		try {
			
			Long last = null;
			
			int match = 0;
			
			for(int i = 0; i < 20; i++) {
				
				long now = ClockDriver.now().getTimestamp();
				
				if(last == null) {
					
					last = now;
					
				} else {
					
					long delta = Math.abs(now - last);
					
					if(delta < 10000) {
						
						match++;
						
						if(match >= 3) {
							
							SystemTime.set(now);
							
							timeSynchronized = true;
							
							log.info("System time synchronized.");
							
							break;
							
						}
						
					} else {
						
						match = 0;
						
					}

				}
				
			}
		
		} catch(Exception e) {
			
			log.warn("Exception occor when synchronize system time", e);
			
		}
		*/
		
	}
	
}
